package com.tcm.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tcm.common.enums.CachePrefix;
import com.tcm.entity.*;
import com.tcm.entity.bo.UserCacheBo;
import com.tcm.entity.dto.param.TestPaperShareParam;
import com.tcm.entity.vo.TestPaperShareListResult;
import com.tcm.exception.DatabaseOperationException;
import com.tcm.exception.EntityInvalidException;
import com.tcm.mapper.TestPaperDetailMapper;
import com.tcm.service.TeacherService;
import com.tcm.service.TestPaperService;
import com.tcm.service.TestPaperShareService;
import com.tcm.mapper.TestPaperShareMapper;
import com.tcm.service.UserService;
import com.tcm.utils.RedisUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
* @author Guqier
* @description 针对表【ts_test_paper_share(试卷分享表)】的数据库操作Service实现
* @createDate 2023-08-02 11:33:41
*/
@Service
public class TestPaperShareServiceImpl extends ServiceImpl<TestPaperShareMapper, TestPaperShare> implements TestPaperShareService{

    public static final int TEST_PAPER_SHARE_PERMANENT_TYPE = 0;// 试卷分享类型，永久

    @Autowired
    private TestPaperService testPaperService;

    @Autowired
    private TestPaperDetailMapper testPaperDetailMapper;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private TeacherService teacherService;

    @Autowired
    private UserService userService;

    /**
     * 向教师分享试卷
     * @param param 参数
     * @param currUserId 当前登录用户ID
     * @return 处理结果，true为成功
     */
    @Override
    @Transactional
    public boolean shareTestPaper(TestPaperShareParam param, Long currUserId){
        // 校验教师是否存在
        List<Long> teacherIds = param.getTeacherIds();
        List<Teacher> teachers = teacherService.listByIds(teacherIds);
        if (teachers.size() != teacherIds.size()){
            throw new EntityInvalidException("教师不存在");
        }
        // 检验试卷是否存在
        TestPaper testPaper = testPaperService.getById(param.getTestPaperId());
        if (testPaper == null) {
            throw new EntityInvalidException("试卷不存在");
        }
        int cnt = 0;// 计数器
        for (Teacher teacher : teachers) {
            // 检验分享目标是否是试卷拥有者
            if (testPaper.getTeacherId().equals(teacher.getId())){
                throw new EntityInvalidException("不能分享给试卷拥有者");
            }
            TestPaperShare testPaperShare = new TestPaperShare();
            BeanUtils.copyProperties(param, testPaperShare);
            testPaperShare.setTeacherId(teacher.getId());
            testPaperShare.setConfirmStatus(0);// 初始化为未确认
            if (testPaperShare.getType().equals(TEST_PAPER_SHARE_PERMANENT_TYPE)){
                // 如果试卷分享为永久，则启用时间为当前时间，失效时间为99年后
                testPaperShare.setEnableTime(new Date());
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(new Date());
                calendar.add(Calendar.YEAR, 99);// 永久
                testPaperShare.setDisableTime(calendar.getTime());
            }
            testPaperShare.setCreateUser(currUserId);
            testPaperShare.setUpdateUser(currUserId);
            if (this.save(testPaperShare)) {
                cnt ++;
            }
        }
        if (cnt != teacherIds.size()){
            throw new DatabaseOperationException("数据库操作失败");
        }
        return true;
    }

    /**
     * 根据当前用户获取已分享列表
     * @param currUserId 当前用户ID
     * @return 已分享列表
     */
    @Override
    public List<TestPaperShareListResult> getSharedList(Long currUserId){
        // 获取指定分享信息
        LambdaQueryWrapper<TestPaperShare> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TestPaperShare::getCreateUser, currUserId);
        List<TestPaperShare> testPaperShareList = this.list(queryWrapper);
        return transferTestPaperShareToListResult(testPaperShareList);
    }

    /**
     * 删除分享
     * @param ids 分享ID列表
     * @return 处理结果，true为成功
     */
    @Override
    @Transactional
    public boolean canselShareTestPaper(List<Long> ids){
        return this.removeByIds(ids);
    }

    /**
     * 将试卷分享实体类转换为列表展示类
     * @param testPaperShareList 试卷分享实体类
     * @return 列表展示类
     */
    @Override
    public List<TestPaperShareListResult> transferTestPaperShareToListResult(List<TestPaperShare> testPaperShareList){
        // 准备数据
        List<Teacher> teacherList = teacherService.list();
        List<TestPaper> testPapers = testPaperService.list();
        List<User> users = userService.list();
        return testPaperShareList.stream().map(testPaperShare -> {
            TestPaperShareListResult result = new TestPaperShareListResult();
            BeanUtils.copyProperties(testPaperShare, result);
            // 查找教师名称
            teacherList.stream().filter(teacher -> teacher.getId().equals(result.getTeacherId())).findFirst().ifPresent(teacher -> result.setTeacherName(teacher.getName()));
            // 查找试卷名称
            testPapers.stream().filter(testPaper -> testPaper.getId().equals(result.getTestPaperId())).findFirst().ifPresent(testPaper -> result.setTestPaperTitle(testPaper.getTitle()));
            // 查找分享人名称
            users.stream().filter(user -> user.getId().equals(testPaperShare.getCreateUser())).findFirst().ifPresent(user -> result.setSharerName(user.getName()));
            return result;
        }).collect(Collectors.toList());
    }

    /**
     * 获取接收到的分享列表
     * @param currUserId 当前登录用户ID
     * @return 取接收到的分享列表
     */
    @Override
    public List<TestPaperShareListResult> getReceivedShareList(Long currUserId){
        // 判断当前登录用户是否是教师
        UserCacheBo userCacheBo = redisUtil.getCacheObject(CachePrefix.PC_USER_TOKEN.getCacheKey(String.valueOf(currUserId)));
        Teacher teacher = teacherService.getTeacherByAccount(userCacheBo.getAccount());
        if (teacher == null) {
            return null;
        }
        // 获取接收到的分享列表
        LambdaQueryWrapper<TestPaperShare> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TestPaperShare::getTeacherId, teacher.getId());
        queryWrapper.orderByDesc(TestPaperShare::getCreateTime);
        return transferTestPaperShareToListResult(this.list(queryWrapper).stream().filter(testPaperShare -> testPaperShare.getEnableTime().getTime() < new Date().getTime()).collect(Collectors.toList()));
    }

    /**
     * 确认接收试卷分享
     * @param shareId 试卷分享ID
     * @param currUserId 当前登录用户ID
     * @return 处理结果，true为成功
     */
    @Override
    @Transactional
    public boolean confirmReceiveShare(Long shareId, Long currUserId){
        // 获取当前用户信息
        UserCacheBo userCacheBo = redisUtil.getCacheObject(CachePrefix.PC_USER_TOKEN.getCacheKey(String.valueOf(currUserId)));
        Teacher teacher = teacherService.getTeacherByAccount(userCacheBo.getAccount());
        if (teacher == null){
            return false;
        }
        // 获取分享信息
        TestPaperShare testPaperShare = this.getById(shareId);
        // 判断是否过期
        Date date = new Date();
        if (testPaperShare.getEnableTime().getTime() < date.getTime() && date.getTime() < testPaperShare.getDisableTime().getTime()){
            // 复制试卷
            TestPaper testPaper = testPaperService.getById(testPaperShare.getTestPaperId());
            TestPaper newTestPaper = new TestPaper();
            newTestPaper.setTeacherId(teacher.getId());
            newTestPaper.setTitle(testPaper.getTitle());
            newTestPaper.setType(testPaper.getType());
            newTestPaper.setCreateUser(currUserId);
            newTestPaper.setUpdateUser(currUserId);
            if (!testPaperService.save(newTestPaper)) {
                throw new DatabaseOperationException("试卷保存失败");
            }
            // 复制试卷详细
            LambdaQueryWrapper<TestPaperDetail> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(TestPaperDetail::getTestPaperId, testPaper.getId());
            List<TestPaperDetail> details = testPaperDetailMapper.selectList(queryWrapper);
            List<TestPaperDetail> testPaperDetails = details.stream().map(detail -> {
                TestPaperDetail testPaperDetail = new TestPaperDetail();
                testPaperDetail.setTestPaperId(newTestPaper.getId());
                testPaperDetail.setType(detail.getType());
                testPaperDetail.setItemId(detail.getItemId());
                testPaperDetail.setSequence(detail.getSequence());
                testPaperDetail.setCreateUser(currUserId);
                testPaperDetail.setUpdateUser(currUserId);
                return testPaperDetail;
            }).collect(Collectors.toList());

            int cnt = 0;// 计数器
            for (TestPaperDetail testPaperDetail : testPaperDetails) {
                if (testPaperDetailMapper.insert(testPaperDetail) == 1) {
                    cnt ++;
                }
            }
            if (cnt != details.size()){
                throw new DatabaseOperationException("试卷详细保存失败");
            }
        }else {
            throw new EntityInvalidException("分享已过期");
        }
        testPaperShare.setConfirmStatus(1);
        testPaperShare.setUpdateUser(currUserId);
        if (!this.updateById(testPaperShare)) {
            throw new DatabaseOperationException("保存分享状态失败");
        }
        return true;
    }

}




